﻿// ============================================================================
// Project: WOOTNETMF - Woot-Off Detector for Netduino Plus
// 
// Description: Utilizes the Netduino Plus to detect if a Woot-Off
//                  is in progress. When detected, a pin is enabled
//                  to signal a set of Woot lights to turn on for
//                  a period of 2 minutes. See http://woot.com for
//                  more information on what a Woot-Off is.
//
// CodePlex Site: http://wootnetmf.codeplex.com
//
// Author: Nithin Shenoy (Twitter: @nitdoggx | Blog: http://repne.wordpress.com)
//
// License: This code is protected by the Apache License 2.0 (Apache).
//              See http://wootnetmf.codeplex.com/license for more information.
// ------------------------------------------------------------
//
// Revision History:
//  [2010-11-14] nithins: Initial checkin
//  [2010-11-21] nithins: Fixed bug to properly use Pins.GPIO_PIN_D0. Also some refactoring and new BlinkSOS() method.
//
// ============================================================================

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using System.Net;
using System.IO;

namespace woot.netmf
{
    public class WootLightController
    {

        #region Static members

        static readonly string _WootUri = "http://www.woot.com/salerss.aspx";       // URL to scrape
        static int _RefreshTime         = 120000;                                   // Time between refreshes
        static OutputPort _LED          = new OutputPort(Pins.ONBOARD_LED, false);  // GPIO pin for switching lights
        
        #endregion

        #region Class methods
        /// <summary>
        /// BlinkSOS() will cause the onboard LED to blink the SOS pattern
        /// </summary>
        static void BlinkSOS()
        {
            int count = 0;
            int i = 0;
            int timeOn = 0;
            int timeOff = 100;

            for (count = 0; count < 3; count++)
            {
                if (count == 1)
                {
                    // The letter is 'O' or '---'
                    timeOn = 600;
                    timeOff = 200;
                }
                else
                {
                    // the letter is 'S' or '...'
                    timeOn = 200;
                    timeOff = 100;
                }

                for (i = 0; i < 3; i++)
                {
                    _LED.Write(true);
                    Thread.Sleep(timeOn);
                    _LED.Write(false);
                    Thread.Sleep(timeOff);

                    if ((count == 0) && (i == 2))
                    {
                        Thread.Sleep(timeOff);
                    }
                }
            }
        }
        #endregion

        #region Main program
        static void Main(string[] args)
        {
            WebRequest webReq = null;
            WebResponse webResp = null;
            Stream wootStream = null;
            StreamReader wootReader = null;
            string currentProduct = "";
            bool fWootOff = false;
            bool fNewProduct = false;
            int wootRefresh = _RefreshTime;
            OutputPort pEnable = null;
            string line = null;

            pEnable = new OutputPort(Pins.GPIO_PIN_D0, false);

            while (true)
            {
                try
                {
                    //
                    // Open reader to woot.com
                    //

                    Debug.Print("Opening webrequest to " + _WootUri);
                    webReq = WebRequest.Create(_WootUri);

                    webResp = webReq.GetResponse();

                    wootStream = webResp.GetResponseStream();
                    wootReader = new StreamReader(wootStream);

                    //
                    // Parse the stream for relevant tags
                    //

                    while (wootReader.Peek() >= 0)
                    {
                        //
                        // Get the next line
                        //

                        try
                        {
                            line = wootReader.ReadLine();
                        }
                        catch (IndexOutOfRangeException e)
                        {
                            continue;
                        }
                        catch (OutOfMemoryException e)
                        {
                            continue;
                        }

                        if (line.Trim().IndexOf("<woot:product ") == 0)
                        {
                            int idxStart = 0;
                            int idxEnd = 0;

                            idxStart = line.IndexOf(">") + 1;
                            idxEnd = line.LastIndexOf("</woot:product>");

                            string newProduct = line.Substring(idxStart, idxEnd - idxStart);
                            if (String.Compare(newProduct, currentProduct) != 0)
                            {
                                Debug.Print("New Product!!");
                                fNewProduct = true;
                                currentProduct = newProduct;
                            }
                            else
                            {
                                Debug.Print("Same product");
                                fNewProduct = false;
                            }
                        }
                        else if (line.Trim().IndexOf("<woot:wootoff>") == 0)
                        {
                            if (line.IndexOf("True") > 0)
                            {
                                Debug.Print("Woot!Off!!!!!");
                                fWootOff = true;
                            }
                            else
                            {
                                Debug.Print("Not a woot off");
                                fWootOff = false;
                            }
                        }
                    } // while

                    //
                    // Close resources
                    //

                    wootReader.Close();
                    wootStream.Close();
                    webResp.Close();

                    if (fWootOff && fNewProduct)
                    {
                        // Turn on lights for 2 minutes
                        Debug.Print("==> Turn on the lights");
                        pEnable.Write(true);
                        _LED.Write(true);
                    }
                    else
                    {
                        pEnable.Write(false);
                        _LED.Write(false);
                    }

                    Debug.Print("Sleeping for " + (wootRefresh / 1000).ToString() + "sec...");

                    Thread.Sleep(wootRefresh);

                    Debug.Print("done sleeping.");
                }
                catch (Exception e)
                {
                    pEnable.Write(false);

                    Debug.Print("Error: " + e.Message);
                    Debug.Print("    Sleeping for 1 minute before trying again due to error...");

                    for (int i = 0; i < 6; i++)
                    {
                        BlinkSOS();
                        Thread.Sleep(10000);
                    }
                    Debug.Print("    Done sleeping due to error.\n\n");
                }
                finally
                {
                    if (wootReader != null)
                    {
                        wootReader.Close();
                    }

                    if (wootStream != null)
                    {
                        wootStream.Close();
                    }
                    
                    if (webResp != null)
                    {
                        webResp.Close();
                    }
                }
            } // while
        }
        #endregion
    }
}
